package cn.edu.sdjzu.xg.eagle.controller;

import cn.edu.sdjzu.xg.eagle.entity.User;
import cn.edu.sdjzu.xg.eagle.entity.authority.Role;
import cn.edu.sdjzu.xg.eagle.entity.authority.UserAssRole;
import cn.edu.sdjzu.xg.eagle.factory.ServiceFactory;
import cn.edu.sdjzu.xg.eagle.service.UserAssRoleService;
import cn.edu.sdjzu.xg.eagle.service.UserService;
import cn.edu.sdjzu.xg.eagle.util.JSONUtil;
import cn.edu.sdjzu.xg.eagle.util.JwtUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户登录控制器
 * 处理用户认证和JWT令牌生成
 */
@Slf4j
@WebServlet("/login.ctl")
public class LoginCtrl extends HttpServlet {
    // 响应键常量
    private static final String MSG_KEY = "msg";
    private static final String CODE_KEY = "code";
    private static final String TOKEN_KEY = "token";
    private static final String ROLES_KEY = "roles";
    private static final String USERNAME_KEY = "username";

    // 响应消息常量
    private static final String SUCCESS_MSG = "登录成功";
    private static final String FAILURE_MSG = "用户名或密码错误";
    private static final String DB_ERROR_MSG = "系统服务异常";
    private static final String PARAM_ERROR_MSG = "请求参数错误";

    // 状态码常量
    private static final int SUCCESS_CODE = 200;
    private static final int FAILURE_CODE = 401;
    private static final int ERROR_CODE = 500;

    // 服务实例
    private final UserService userService = ServiceFactory.getService(UserService.class, "UserServiceImpl");
    private final UserAssRoleService userAssRoleService = ServiceFactory.getService(UserAssRoleService.class, "UserAssRoleServiceImpl");

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        JSONObject responseJson = new JSONObject();

        try {
            // 1. 参数校验和解析
            String userJson = JSONUtil.getJSON(request);
            if (userJson == null || userJson.isEmpty()) {
                buildResponse(responseJson, PARAM_ERROR_MSG, FAILURE_CODE, null);
                response.getWriter().println(responseJson.toJSONString());
                return;
            }

            User loginUser = JSON.parseObject(userJson, User.class);
            if (loginUser == null || loginUser.getUsername() == null || loginUser.getPassword() == null) {
                buildResponse(responseJson, PARAM_ERROR_MSG, FAILURE_CODE, null);
                response.getWriter().println(responseJson.toJSONString());
                return;
            }
            // 使用 @Slf4j 注解注入日志对象
            // 记录用户登录请求，动态插入用户名
            // 日志格式中的 "{}" 是占位符，用于插入 loginUser.getUsername() 的值
            // 该日志用于审计用户登录行为，便于后续追踪和调试
            log.info("User login request: username={}", loginUser.getUsername());

            // 2. 用户认证
            userService.login(loginUser);
            if (loginUser.getId() == null) {
                log.warn("User authentication failed: username={}", loginUser.getUsername());
                buildResponse(responseJson, FAILURE_MSG, FAILURE_CODE, null);
                response.getWriter().println(responseJson.toJSONString());
                return;
            }

            // 3. 获取用户完整信息和角色
            User currentUser = userService.find(loginUser.getId());
            List<String> roles = getUserRoles(currentUser);

            // 4. 生成JWT令牌，并放入响应头
            String token = JwtUtil.signToken(
                    JwtUtil.generateBuilder()
                            .withSubject(String.valueOf(currentUser.getId()))
                            .withClaim(USERNAME_KEY, currentUser.getUsername())
                            .withClaim(ROLES_KEY, roles)
            );
            response.setHeader("Authorization", token);  // 标准格式：Bearer <token>

            // 5. 构建成功响应
            JSONObject data = new JSONObject();
            data.put(ROLES_KEY, roles);
            data.put(USERNAME_KEY, currentUser.getUsername());

            buildResponse(responseJson, SUCCESS_MSG, SUCCESS_CODE, data);
            response.getWriter().println(responseJson.toJSONString());

            log.info("User login successful: userId={}, username={}", currentUser.getId(), currentUser.getUsername());
        } catch (SQLException e) {
            log.error("Database exception occurred", e);
            buildResponse(responseJson, DB_ERROR_MSG, ERROR_CODE, null);
            response.getWriter().println(responseJson.toJSONString());
        } catch (Exception e) {
            log.error("System exception occurred", e);
            buildResponse(responseJson, DB_ERROR_MSG, ERROR_CODE, null);
            response.getWriter().println(responseJson.toJSONString());
        }
    }

    /**
     * 获取用户角色列表
     */
    private List<String> getUserRoles(User user) throws SQLException {
        // 获取用户关联的所有角色
        Collection<UserAssRole> userAssRoles = userAssRoleService.findAll(user);
        // 创建结果列表
        List<String> roleDescriptions = new ArrayList<>();
        // 遍历每个用户角色关联
        for (UserAssRole userAssRole : userAssRoles) {
            // 获取角色对象
            Role role = userAssRole.getRole();
            // 获取角色描述并添加到结果列表
            roleDescriptions.add(role.getDescription());
        }
        return roleDescriptions;
    }

    /**
     * 构建统一响应格式
     */
    private void buildResponse(JSONObject responseJson, String message, int code, JSONObject data) {
        responseJson.put(MSG_KEY, message);
        responseJson.put(CODE_KEY, code);
        if (data != null) {
            responseJson.put("data", data);
        }
    }
}